#include <stdio.h>
#include "normalized_datatypes.h"
#include "normalization_globals.h"
#include "print_utils.h"

void print_normalized_atomic_concept(NormalizedAtomicConcept* ac);
void print_normalized_exists(NormalizedExists* exists);
void print_normalized_conjunction(NormalizedConjunction* conjunction);
void print_normalized_atomic_role(NormalizedAtomicRole* ar);

void print_normalized_concept(NormalizedConcept* c) {
	switch (c->type) {
		case NORMALIZED_ATOMIC_CONCEPT:
			print_normalized_atomic_concept(c->description.atomic);
			break;
		case NORMALIZED_EXISTENTIAL_RESTRICTION:
			print_normalized_exists(c->description.exists);
			break;
		case NORMALIZED_CONJUNCTION:
			print_normalized_conjunction(c->description.conj);
			break;
		default:
			fprintf(stderr,"unknown normalized concept type, aborting\n");
			exit(-1);
	}
}

void print_normalized_role(NormalizedRole* r) {
	switch (r->type) {
		case NORMALIZED_ATOMIC_ROLE:
			print_normalized_atomic_role(r->description.atomic);
			break;
		default:
			fprintf(stderr,"unknown role type, aborting\n");
			exit(-1);
	}
}
	
void print_normalized_atomic_concept(NormalizedAtomicConcept* ac) {
        printf("%s ", ac->name);
}

void print_normalized_exists(NormalizedExists* ex) {
	printf("(Some ");
	print_normalized_role(ex->role);
	printf(" ");
	print_normalized_concept(ex->filler);
	printf(")");
}

void print_normalized_conjunction(NormalizedConjunction* conj) {
	printf("(And ");
	Word_t index = 0;
	int judy_return;
	J1F(judy_return,conj->conjuncts,index);
	if (judy_return == 0) {
		fprintf(stderr,"no conjunct in conjunction, aborting\n");
		exit(-1);
	}
	while (judy_return == 1) {
		print_normalized_concept((NormalizedConcept*) index);
		printf(" ");
		
		J1N(judy_return,conj->conjuncts,index);
	}
	printf(")");
}

void print_normalized_atomic_role(NormalizedAtomicRole* ar) {
        printf("%s ", ar->name);
}

void print_normalized_subclass_axiom(NormalizedSubClassAxiom* sc_ax) {
	printf("(SubClassOf ");
	print_normalized_concept(sc_ax->lhs);
	printf(", ");
	print_normalized_concept(sc_ax->rhs);
	printf(")\n");
}

// TODO
void print_normalized_subrole_axiom(NormalizedSubRoleAxiom* ri_ax) {
	printf("(RoleInclusion\n");
}

void print_normalized_axiom(NormalizedAxiom* ax) {
	switch (ax->type) {
		case NORMALIZED_SUBCLASS_AX:
			print_normalized_subclass_axiom(ax->body.subclass_ax);
			break;
		case NORMALIZED_SUBROLE_AX:
			print_normalized_subrole_axiom(ax->body.subrole_ax);
			break;
		default:
			fprintf(stderr, "unknown axiom type, aborting\n");
			exit(-1);
	}
}

void print_normalized_tbox() {
	int i;
	for (i = 0; i < normalized_tbox.axiom_count ; ++i)
		print_normalized_axiom(normalized_tbox.axioms[i]);
}

void print_normalization_stats() {
        printf("---------- Normalization statistics ----------\n");
        printf("new atomic concepts on the lhs: %d\nnew atomic concepts on the rhs:%d\ngenerated existentail restrictions:%d\nnormalized subclass axioms in total: %d\nsingleton premise count: %d\nmax lhs size: %d\nmax rhs size: %d\navg lhs size: %.3f\navg rhs size: %.3f\n", generated_atomic_concepts_left_count, generated_atomic_concepts_right_count, generated_exists_restriction_count, generated_subclass_axiom_count, singleton_premise_count, max_lhs_size, max_rhs_size, (double) cum_lhs_size / generated_subclass_axiom_count, (double) cum_rhs_size / generated_subclass_axiom_count);
}
